package com.suxin.thread;

import sun.misc.Unsafe;

import java.lang.reflect.Field;
import java.security.AccessController;
import java.security.PrivilegedExceptionAction;

/**
 * @author Tang
 * @classname ThreadTest
 * @description [  ]
 * @date 2021/4/6 20:43
 */
public class ThreadTest {

    static Field fThreadLocalRandomSeed;
    static sun.misc.Unsafe UNSAFE;
    private static long SEED;

    static {
        try {
            // 获得unsafe对象
            fThreadLocalRandomSeed = Thread.class.getDeclaredField("threadLocalRandomSeed");
            final PrivilegedExceptionAction<Unsafe> action = new PrivilegedExceptionAction<Unsafe>() {
                @Override
                public Unsafe run() throws Exception {
                    Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
                    theUnsafe.setAccessible(true);
                    // 静态字段 传null
                    return (Unsafe) theUnsafe.get(null);
                }
            };
            UNSAFE = AccessController.doPrivileged(action);
            Class<?> tk = Thread.class;
            SEED = UNSAFE.objectFieldOffset(tk.getDeclaredField("threadLocalRandomSeed"));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws Exception{
        for (int i = 0; i < 10; i++) {
            byUnsafe();
            byReflection();
        }
        System.out.println("====================");
        byUnsafe();
        byReflection();
    }

    public static void byReflection() throws Exception{
        long start = System.currentTimeMillis();
        Thread thread = Thread.currentThread();
        fThreadLocalRandomSeed.setAccessible(true);
        fThreadLocalRandomSeed.set(thread, 0);
        for (int i = 0; i < 10000000; i++) {
            fThreadLocalRandomSeed.set(thread,(Long)fThreadLocalRandomSeed.get(thread) + 1);
        }
        long end = System.currentTimeMillis();
        System.out.println("byReflection sped:" + (end - start) + "ms");
    }

    public static void byUnsafe() {
        long start = System.currentTimeMillis();
        UNSAFE.putLong(Thread.currentThread(),SEED,0);
        Thread thread = Thread.currentThread();
        for (int i = 0; i < 10000000; i++) {
            UNSAFE.putLong(thread,SEED,UNSAFE.getLong(thread,SEED));
        }
        long end = System.currentTimeMillis();
        System.out.println("byUnsafe sped:" + (end - start) + "ms");
    }

}